/*
 * 服务器列表类，处理服务器列表
 */
package labox.innovation.loginserver.socket.serverpackets;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import javolution.util.FastList;
import labox.innovation.config.Config;
import labox.innovation.db.core.L2DatabaseFactory;
import labox.innovation.loginserver.GameServerTable;
import labox.innovation.loginserver.GameServerTable.GameServerInfo;
import labox.innovation.loginserver.gameserverpackets.ServerStatus;
import labox.innovation.loginserver.socket.LoginClient;

/**
 * ServerList Format: cc [cddcchhcdc]
 * 
 * c: server list size (number of servers) c: ? [ (repeat for each servers) c: server id (ignored by client?) d: server ip d: server port c: age limit (used by client?) c: pvp or not (used by client?) h: current number of players h: max number of players c: 0 if server is down d: 2nd bit: clock 3rd bit: wont dsiplay server name 4th bit: test server (used by client?) c: 0 if you dont want to display brackets in front of sever name ]
 * 
 * Server will be considered as Good when the number of online players is less than half the maximum. as Normal between half and 4/5 and Full when there's more than 4/5 of the maximum number of players
 */
public final class ServerList extends LoginServerPacket {
	private List<ServerData> _servers;

	private HashMap<Integer, Integer> _characters;

	private int _sessionId;

	class ServerData {
		protected String _ip;

		protected int _port;

		protected int _status;

		protected int _serverId;

		protected String _serverName;

		protected int _playerCount;

		protected int _serverType;

		protected int _maxPlayers;

		ServerData(String pIp, int pPort, int pStatus, int pServer_id, String serverName, int playerCount, int serverType, int maxPlayers) {
			_ip = pIp;
			_port = pPort;
			_status = pStatus;
			_serverId = pServer_id;
			_serverName = serverName;
			_playerCount = playerCount;
			_serverType = serverType;
			_maxPlayers = maxPlayers;
		}
	}

	private void buildCharactersMap(String account) {
		Connection con = null;
		PreparedStatement statement = null;

		try {
			con = L2DatabaseFactory.getInstance().getConnection();
			statement = con.prepareStatement("SELECT * FROM charactercountsofaccount where account = ? ");
			statement.setString(1, account);
			ResultSet rs = statement.executeQuery();
			while (rs.next()) {
				_characters.put(rs.getInt("server_id"), rs.getInt("count"));
			}
			rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				statement.close();
				con.close();
			} catch (Exception e) {
				if (Config.DEBUG)
					e.printStackTrace();
			}

		}
	}

	public ServerList(LoginClient client) {
		_servers = new FastList<ServerData>();
		_characters = new HashMap<Integer, Integer>();
		_sessionId = client.getSessionKey();
		for (GameServerInfo gsi : GameServerTable.getInstance().getRegisteredGameServers().values()) {
			if (gsi.getStatus() == ServerStatus.STATUS_GM_ONLY) {
				if (client.getAccessLevel() > 0) {
					addServer(client.usesInternalIP() ? gsi.getInternalIp() : gsi.getExternalIp(), gsi.getPort(), gsi.getStatus(), gsi.getId(), gsi.getExternalHost(), gsi.getPlayCount(), gsi.getType(), gsi.getMaxPlayers());
				} else {
					addServer(client.usesInternalIP() ? gsi.getInternalIp() : gsi.getExternalIp(), gsi.getPort(), ServerStatus.STATUS_DOWN, gsi.getId(), gsi.getExternalHost(), gsi.getPlayCount(), gsi.getType(), gsi.getMaxPlayers());
				}
			} else {
					addServer(client.usesInternalIP() ? gsi.getInternalIp() : gsi.getExternalIp(), gsi.getPort(), gsi.getStatus(), gsi.getId(), gsi.getExternalHost(), gsi.getPlayCount(), gsi.getType(), gsi.getMaxPlayers());
			}
		}

		buildCharactersMap(client.getAccount());
	}

	private void addServer(String ip, int port, int status, int server_id, String serverName, int playerCount, int serverType, int maxPlayers) {
		_servers.add(new ServerData(ip, port, status, server_id, serverName, playerCount, serverType, maxPlayers));
	}

	@Override
	public void write() {
		writeByte(PTL_SERVERLIST);
		writeInt(_sessionId);
		writeByte(_servers.size());
		StringBuilder sb = new StringBuilder();

		for (ServerData server : _servers) {
			writeByte((char) (server._serverId + '0'));

			writeByte(server._serverType);
			if (server._serverName == null || server._serverName.length() == 0) {
				writeString(server._ip);
			} else {
				writeString(server._serverName);
			}

			sb.setLength(0);
			sb.append("socket://").append(server._ip).append(':').append(server._port);

			writeString(sb.toString());

			if (_characters.size() > 0 && _characters.get(server._serverId) != null) {
				writeByte(_characters.get(server._serverId));
			} else
				writeByte(0);

			writeByte(server._status);

		}
	}
}
